package com.agmte.api.common.crud.tableAutoCreate;

import com.agmte.api.common.crud.annotation.TableAnno;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.*;

public class AnnotationScanner {


    public static void main(String[] args) throws ClassNotFoundException {
//        // 扫描指定包下所有带有@TableInfo注解的类
//        List<Class<?>> annotatedClasses = AnnotationScanner.findAnnotatedClasses(
//                "com.agmte.api", TableAnno.class);
//
//        // 输出结果
//        for (Class<?> clazz : annotatedClasses) {
//            TableAnno annotation = clazz.getAnnotation(TableAnno.class);
//            String tableName = annotation.value().isEmpty() ? clazz.getSimpleName() : annotation.value();
//            System.out.println("类名: " + clazz.getName() + ", 表名: " + tableName);
//        }
        Set<Class<?>> annotatedClassesV2 = findAnnotatedClassesV2("com.agmte.api", TableAnno.class);
    }

    public static Set<Class<?>> findAnnotatedClassesV2(String packageName, Class<? extends Annotation> annotationClass) {
        Set<Class<?>> annotatedClasses = new HashSet<>();

        // 1. 创建扫描器，false表示不使用默认的@Component等注解过滤器
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);

        // 2. 添加只扫描带@TableAnno注解的过滤器
        scanner.addIncludeFilter(new AnnotationTypeFilter(annotationClass));

        // 3. 扫描指定包内所有符合过滤器条件的bean定义（即类）

        for (BeanDefinition beanDef : scanner.findCandidateComponents(packageName)) {
            String className = beanDef.getBeanClassName();
            if (className != null) {
                try {
                    Class<?> clazz = Class.forName(className);
                    annotatedClasses.add(clazz);
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }

            }
        }
        return annotatedClasses;
    }

    /**
     * 扫描指定包下所有带有指定注解的类
     *
     * @param packageName     包名
     * @param annotationClass 注解类
     * @return 带有指定注解的类列表
     */
    public static List<Class<?>> findAnnotatedClasses(String packageName, Class<? extends Annotation> annotationClass) {
        List<Class<?>> annotatedClasses = new ArrayList<>();

        try {
            // 获取包下的所有类
            List<Class<?>> allClasses = getClasses(packageName);

            // 筛选带有指定注解的类
            for (Class<?> clazz : allClasses) {
                if (clazz.isAnnotationPresent(annotationClass)) {
                    annotatedClasses.add(clazz);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return annotatedClasses;
    }

    /**
     * 获取包下的所有类
     */
    private static List<Class<?>> getClasses(String packageName)
            throws ClassNotFoundException, IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = classLoader.getResources(path);

        List<File> dirs = new ArrayList<>();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            dirs.add(new File(resource.getFile()));
        }

        List<Class<?>> classes = new ArrayList<>();
        for (File directory : dirs) {
            classes.addAll(findClasses(directory, packageName));
        }

        return classes;
    }

    /**
     * 递归查找目录下的所有类
     */
    private static List<Class<?>> findClasses(File directory, String packageName)
            throws ClassNotFoundException {
        List<Class<?>> classes = new ArrayList<>();

        if (!directory.exists()) {
            return classes;
        }

        File[] files = directory.listFiles();
        if (files == null) {
            return classes;
        }

        for (File file : files) {
            if (file.isDirectory()) {
                // 递归处理子目录
                classes.addAll(findClasses(file, packageName + "." + file.getName()));
            } else if (file.getName().endsWith(".class")) {
                // 处理类文件
                String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                Class<?> clazz = Class.forName(className);
                classes.add(clazz);
            }
        }

        return classes;
    }
}
